﻿using SCM.Common;
using SCM.Common.Extensions;
using SCM.Model;
using SCM.Model.DBEntity;
using SCM.Servie.IBusiness;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace SCM.Servie.Business
{
    /// <summary>
    /// 用户服务
    /// </summary>
    public class UserService : IUserService
    {
        private readonly DbContext dal = new DbContext();

        public bool Add(AddUpdateUserVo model)
        {
            try
            {
                dal.BeginTran();

                T_User user = new T_User();
                user.ID = Guid.NewGuid().ToString();
                user.CompanyID = model.CompanyID;
                user.UserAccount = model.UserAccount;
                user.UserDisplayName = model.UserDisplayName;
                user.UserPassword = model.UserPassword;
                user.UserType = model.UserType;
                user.DataStatus = model.DataStatus;
                user.Creator = model.Creator;
                user.CreatorName = model.CreatorName;
                bool result = dal.Insert(user);
                if (result == false)
                {
                    dal.RollbackTran();
                    return false;
                }

                T_User_Role userRole = new T_User_Role();
                userRole.ID = Guid.NewGuid().ToString();
                userRole.CompanyID = model.CompanyID;
                userRole.UserID = user.ID;
                userRole.RoleID = model.RoleID;

                result = dal.Insert(userRole);
                if (result == false)
                {
                    dal.RollbackTran();
                    return false;
                }

                dal.CommitTran();
                return true;
            }
            catch (Exception ex)
            {
                dal.RollbackTran();
                throw ex;
            }
        }

        public bool Delete(List<string> ids)
        {
            try
            {
                dal.BeginTran();

                bool result = dal.Updateable<T_User>(new
                {
                    DataStatus = DataStatusEnum.Deleted,
                    ModifyTime = DateTime.Now,
                }).Where(p => ids.Contains(p.ID)).ExecuteCommand() > 0;

                if (result == false)
                {
                    dal.RollbackTran();
                    return false;
                }

                result = dal.Delete<T_User_Role>(p => ids.Contains(p.UserID));

                if (result == false)
                {
                    dal.RollbackTran();
                    return false;
                }

                dal.CommitTran();
                return true;
            }
            catch (Exception ex)
            {
                dal.RollbackTran();
                throw ex;
            }
        }

        public AddUpdateUserVo GetById(string id)
        {
            var result = dal.Queryable<T_User, T_User_Role>((a, b) => new object[]
            {
                JoinType.Left,a.ID == b.UserID && a.DataStatus == DataStatusEnum.Valid,
            })
           .Where((a, b) => a.ID == id && a.DataStatus == DataStatusEnum.Valid)
           .Select((a, b) => new AddUpdateUserVo()
           {
               ID = a.ID,
               CompanyID = a.CompanyID,
               UserAccount = a.UserAccount,
               UserDisplayName = a.UserDisplayName,
               RoleID = b.RoleID
           }).First();
            return result;
        }

        public T_User GetByUserAccount(string userAccount, string password)
        {
            return dal.QueryOne<T_User>(p => p.UserAccount == userAccount && p.UserPassword == password && p.DataStatus != DataStatusEnum.Deleted);
        }

        public List<QueryUserVo> GetList(string companyId)
        {
            Expression<Func<T_User, T_User_Role, T_Role, T_Company, bool>> whereExp = (a, b, c, d) => a.DataStatus == DataStatusEnum.Valid && a.UserType != UserTypeEnum.SuperAdmin;
            if (!string.IsNullOrWhiteSpace(companyId))
            {
                whereExp = whereExp.Compose((a, b, c, d) => a.CompanyID == companyId, Expression.AndAlso);
            }
            return dal.Queryable<T_User, T_User_Role, T_Role, T_Company>((a, b, c, d) => new object[]
            {
                JoinType.Left,a.ID == b.UserID,
                JoinType.Left,b.RoleID == c.ID,
                JoinType.Left,a.CompanyID == d.ID
            })
            .Where(whereExp)
            .OrderBy(a => a.CreateTime, OrderByType.Desc)
            .Select((a, b, c, d) => new QueryUserVo()
            {
                ID = a.ID,
                CompanyID = a.CompanyID,
                UserAccount = a.UserAccount,
                UserDisplayName = a.UserDisplayName,
                UserType = a.UserType,
                CreateTime = a.CreateTime,
                DataStatus = a.DataStatus,
                CompanyName = d.CompanyName,
                RoleDescription = c.RoleDescription
            }).ToList();
        }

        public PageData<QueryUserVo> Query(string companyId, string userAccount, string displayName, PageInfo page)
        {
            int totalCount = 0;
            Expression<Func<T_User, T_User_Role, T_Role, T_Company, bool>> whereExp = (a, b, c, d) => a.UserType != UserTypeEnum.SuperAdmin && (a.DataStatus == DataStatusEnum.Valid);
            if (!string.IsNullOrWhiteSpace(companyId))
            {
                whereExp = whereExp.Compose((a, b, c, d) => a.CompanyID == companyId, Expression.AndAlso);
            }

            if (!string.IsNullOrWhiteSpace(userAccount))
            {
                whereExp = whereExp.Compose((a, b, c, d) => a.UserAccount.StartsWith(userAccount), Expression.AndAlso);
            }

            if (!string.IsNullOrWhiteSpace(displayName))
            {
                whereExp = whereExp.Compose((a, b, c, d) => a.UserDisplayName.StartsWith(displayName), Expression.AndAlso);
            }

            var list = dal.Queryable<T_User, T_User_Role, T_Role, T_Company>((a, b, c, d) => new object[]
            {
                JoinType.Left,a.ID == b.UserID,
                JoinType.Left,b.RoleID == c.ID,
                JoinType.Left,a.CompanyID == d.ID
            })
            .Where(whereExp)
            .OrderBy(a => a.CreateTime, OrderByType.Desc)
            .Select((a, b, c, d) => new QueryUserVo()
            {
                ID = a.ID,
                CompanyID = a.CompanyID,
                UserAccount = a.UserAccount,
                UserDisplayName = a.UserDisplayName,
                UserType = a.UserType,
                CreateTime = a.CreateTime,
                DataStatus = a.DataStatus,
                CompanyName = d.CompanyName,
                RoleDescription = c.RoleDescription
            })
            .ToPageList(page.PageIndex, page.PageSize, ref totalCount);
            page.DataCount = totalCount;
            return new PageData<QueryUserVo>() { Data = list, Page = page };
        }

        public bool Update(AddUpdateUserVo model)
        {
            try
            {
                dal.BeginTran();

                bool result = dal.Updateable<T_User>(p => new T_User()
                {
                    UserPassword = model.UserPassword,
                    ModifyUserId = model.ModifyUserId,
                    ModifyUserName = model.ModifyUserName,
                }).Where(p => p.ID == model.ID).ExecuteCommand() > 0;
                if (result == false)
                {
                    dal.RollbackTran();
                    return false;
                }

                result = dal.Delete<T_User_Role>(p => p.UserID == model.ID && p.RoleID == model.RoleID);
                if (result == false)
                {
                    dal.RollbackTran();
                    return false;
                }

                T_User_Role userRole = new T_User_Role();
                userRole.ID = Guid.NewGuid().ToString();
                userRole.CompanyID = model.CompanyID;
                userRole.UserID = model.ID;
                userRole.RoleID = model.RoleID;

                result = dal.Insert(userRole);
                if (result == false)
                {
                    dal.RollbackTran();
                    return false;
                }

                dal.CommitTran();
                return true;
            }
            catch (Exception ex)
            {
                dal.RollbackTran();
                throw ex;
            }
        }

        public bool Registe(LoginRegisteVo model)
        {
            try
            {
                dal.BeginTran();

                //添加企业
                T_Company company = new T_Company();
                company.ID = Guid.NewGuid().ToString();
                company.CompanyName = model.CompanyName;
                company.ShortName = model.ShortName;
                company.IdentityNumber = model.IdentityNumber;
                company.TelPhone = model.TelPhone;
                company.Email = model.Email;
                company.PhoneIsVerify = 0;
                company.EmailIsVerify = 0;
                company.ValidDate = model.ValidDate;
                company.Contacter = model.Contacter;
                company.DataStatus = model.DataStatus;
                company.Creator = model.Creator;
                company.CreatorName = model.CreatorName;
                bool result = dal.Insert(company);
                if (result == false)
                {
                    dal.RollbackTran();
                    return false;
                }

                //添加用户
                T_User user = new T_User();
                user.ID = Guid.NewGuid().ToString();
                user.CompanyID = company.ID;
                user.UserAccount = company.TelPhone;
                user.UserDisplayName = model.UserDisplayName;
                user.UserPassword = model.UserPassword;
                user.UserType = model.UserType;
                user.DataStatus = model.DataStatus;
                user.Creator = model.Creator;
                user.CreatorName = model.CreatorName;
                result = dal.Insert(user);
                if (result == false)
                {
                    dal.RollbackTran();
                    return false;
                }

                //添加用户所属权限
                T_User_Role userRole = new T_User_Role();
                userRole.ID = Guid.NewGuid().ToString();
                userRole.CompanyID = company.ID;
                userRole.UserID = user.ID;
                userRole.RoleID = model.RoleID;
                result = dal.Insert(userRole);
                if (result == false)
                {
                    dal.RollbackTran();
                    return false;
                }

                dal.CommitTran();
                return true;
            }
            catch (Exception ex)
            {
                dal.RollbackTran();
                throw ex;
            }
        }

        public LoginResultVo Login(string userAccount, string password)
        {
            var result = dal.Queryable<T_User, T_User_Role, T_Role, T_Company>((a, b, c, d) => new object[]
            {
                JoinType.Inner,a.ID == b.UserID && a.DataStatus == DataStatusEnum.Valid,
                JoinType.Inner,b.RoleID == c.ID && c.DataStatus== DataStatusEnum.Valid,
                JoinType.Inner,a.CompanyID == d.ID && d.DataStatus == DataStatusEnum.Valid
            })
           .Where((a, b, c, d) => a.UserAccount == userAccount && a.UserPassword == password && a.DataStatus == DataStatusEnum.Valid && c.DataStatus == DataStatusEnum.Valid && d.DataStatus == DataStatusEnum.Valid)
           .Select((a, b, c, d) => new LoginResultVo()
           {
               UserID = a.ID,
               UserDisplayName = a.UserDisplayName,
               RoleID = SqlFunc.IsNull(c.ID, ""),
               RoleNameDescription = SqlFunc.IsNull(c.RoleDescription, ""),
               CompanyID = d.ID,
               CompanyName = d.CompanyName,
               ValidDate = d.ValidDate
           }).First();
            return result;
        }

        public bool UpdatePwd(T_User model)
        {
            return dal.Updateable<T_User>(p => new T_User()
            {
                UserPassword = model.UserPassword,
                ModifyUserId = model.ModifyUserId,
                ModifyUserName = model.ModifyUserName,
            }).Where(p => p.ID == model.ID).ExecuteCommand() > 0;
        }
    }
}
